function OSGBModel(parent, name, meshData, textureData, lodRanges, rangeDatas) {

	THREE.Mesh.call( this );

	this.type = 'OSGBModel';

	this.parent = parent;
	this.name = name;

	this.meshData = meshData;
	this.textureData = textureData;
	this.lodRanges = lodRanges;
	this.rangeDatas = rangeDatas;

	this.geometry = null;
	this.material = null;
	this.texture = null;
	this.mesh = null;
}

OSGBModel.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), {

	constructor: OSGBModel,

	getWorldBoundingBox: function () {
		return this.geometry.boundingBox;
	},

	doCreate: function () {
		if (this.geometry == null && this.material == null) {
			var geometry = new THREE.BufferGeometry();
			geometry.setAttribute('position', new THREE.BufferAttribute(this.meshData.positions, 3));
			geometry.setAttribute('uv', new THREE.BufferAttribute(this.meshData.texCoords, 2));
			geometry.setIndex(new THREE.Uint16BufferAttribute(this.meshData.indexs, 1));
			geometry.boundingSphere = new THREE.Sphere(new THREE.Vector3(this.meshData.sphereBox[0], this.meshData.sphereBox[1], this.meshData.sphereBox[2]), this.meshData.sphereBox[3]);
			geometry.boundingBox = new THREE.Box3(new THREE.Vector3(this.meshData.boundingBox[0], this.meshData.boundingBox[1], this.meshData.boundingBox[2]), new THREE.Vector3(this.meshData.boundingBox[3], this.meshData.boundingBox[4], this.meshData.boundingBox[5]));
			//geometry.computeBoundingSphere();

			var texture = null;
			if (this.textureData.compress == 0) {
				texture = new THREE.DataTexture(this.textureData.data, this.textureData.width, this.textureData.height, this.textureData.format, this.textureData.type);
			} else {
				texture = new THREE.CompressedTexture(this.textureData.mipmaps, this.textureData.width, this.textureData.height, this.textureData.format, this.textureData.type);
			}
			texture.wrapS = THREE.ClampToEdgeWrapping;
			texture.wrapT = THREE.ClampToEdgeWrapping;
			texture.magFilter = THREE.LinearFilter;
			texture.minFilter = THREE.LinearFilter;
			texture.generateMipmaps = false;
			texture.needsUpdate = true;

			var material = new THREE.ShaderMaterial({
				uniforms:
					{
						texture: { value: texture },
					},
				vertexShader:   document.getElementById( 'textureVertexShader'   ).textContent,
				fragmentShader: document.getElementById( 'textureFragmentShader' ).textContent,
				side: THREE.FrontSide,
				transparent: false
			});

			this.mesh = new THREE.Mesh(geometry, material);
			this.mesh.rotation.x = -Math.PI/2;

			this.geometry = geometry;
			this.material = material;
			this.texture = texture;

			this.parent.add(this);
		}
		return this.geometry;
	},

	doDestroy: function () {
		if (this.geometry != null) {
			this.geometry.dispose();
			this.geometry = null;
		}
		if (this.material != null) {
			this.material.dispose();
			this.material = null;
		}
		if (this.texture != null) {
			this.texture.dispose();
			this.texture = null;
		}

		this.parent.remove(this);
	},

	setActive: function (active) {
		if (active) {
			if (this.geometry == null) {
				this.geometry = this.createObject(this.parent, this.name);
			}
			this.visible = true;
		} else {
			// if (this.geometry != null) {
			// 	this.geometry.dispose();
			// 	this.geometry = null;
			// }
			// if (this.material != null) {
			// 	this.material.dispose();
			// 	this.material = null;
			// }
			// if (this.texture != null) {
			// 	this.texture.dispose();
			// 	this.texture = null;
			// }
			this.visible = false;
		}
	},

	createObject: function (parent, name) {
		return this.doCreate();
	},

} );

